package com.syezon.wifikey.ad;

import android.text.TextUtils;

import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.SPUtils;
import com.hodanet.appadvplatclient.ad.AdInfo;
import com.syezon.wifikey.utils.DateUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class CommonAdConfig {
    private String configName;
    private final String LAST_SPLASH_SHOW_DAY = "last_splash_show_day";
    private List<AdInfo> mPopAdOrderList;
    private HashMap<Integer, List<AdInfo>> maps;
    private final String SHOWED_POP_AD_IDS = "showedADIds";
    //上次显示的广告
    private final String LAST_AD_CODE = "last_ad_code";
    //上次本地填充的广告的type
    private static final String LAST_AD_OLD_TYPE = "last_ad_old_type";
    private static final String SHOW_AD_ORDER = "splash_ad_order";
    //填充的广告
    private static final String AD_SOURCE_SELF = "ZY";
    private static final String AD_SOURCE_GDT = "GDT";
    private static final String AD_SOURCE_TT = "CSJ";
    private static final String AD_SOURCE_DEFAULT = "default";
    public static final String DEFAULT_AD_ORDER = "CSJ,GDT,ZY";

    public List<AdInfo> getAdList() {
        return mPopAdOrderList;
    }

    public CommonAdConfig(String name) {
        this.configName = name;
    }


    private int getLastSplashAdCodeInt() {
        int currentDayInt = DateUtil.getDayInt(new Date());
        int lastShowDayInt = SPUtils.getInstance(configName).getInt(LAST_SPLASH_SHOW_DAY, 0);
        if (lastShowDayInt == currentDayInt) {
            return SPUtils.getInstance(configName).getInt(LAST_AD_CODE, -1);
        } else {
            return -1;
        }
    }

    private static void clearSelfAD(List<AdInfo> adOrderList) {
        boolean showSelfAd = AdConfig.canShowSelfAd();
        if (!showSelfAd) {
            for (int i = 0; i < adOrderList.size(); i++) {
                AdInfo currentAd = adOrderList.get(i);
                if (currentAd.getType() == AdInfo.AD_TYPE_WEB || currentAd.getType() == AdInfo.AD_TYPE_APK || currentAd.getType() == AdInfo.AD_TYPE_DEEPLINK) {
                    adOrderList.remove(i);
                    i--;
                }
            }
        }
    }

    public void setAdList(List<AdInfo> popAdOrderList) {
        Collections.sort(popAdOrderList);
        clearSelfAD(popAdOrderList);
        mPopAdOrderList = popAdOrderList;
        queryAllShowedAdsIdAndSetStatus();
        toMap(mPopAdOrderList);
    }

    /**
     * 查询对应已经显示过的广告，并且设置对应的状态
     */
    private void queryAllShowedAdsIdAndSetStatus() {
        //本地获取所有显示过的广告id
        String showedAdIds = getShowedAdIds();
        //本地没有广告id，则直接return
        if (TextUtils.isEmpty(showedAdIds)) {
            return;
        }
        //有则进行切割
        String[] adIds = showedAdIds.split(",");
        //如果广告id的长度和集合数组的长度不符合，那么直接清空本地的id缓存
        if (adIds.length >= mPopAdOrderList.size()) {
            clearShowedAdIds();
        } else {
            //否则开始循环，将对应id的AdInfo进行设置showed的状态
            for (String adId : adIds) {
                AdInfo adInfo = new AdInfo();
                adInfo.setId(Integer.parseInt(adId));
                int index = mPopAdOrderList.indexOf(adInfo);
                if (index != -1) {
                    mPopAdOrderList.get(index).setShowed(true);
                }
            }
        }
    }

    private void clearShowedAdIds() {
        SPUtils.getInstance(configName).put(SHOWED_POP_AD_IDS, "");
    }


    private void toMap(List<AdInfo> mPopAdOrderList) {
        maps = new HashMap<>();
        Collections.sort(mPopAdOrderList);
        for (AdInfo adInfo : mPopAdOrderList) {
            List<AdInfo> adInfos = maps.get(adInfo.getOrder());
            if (adInfos == null) {
                adInfos = new ArrayList<>();
                maps.put(adInfo.getOrder(), adInfos);
            }
            adInfos.add(adInfo);
        }
    }

    private String getShowedAdIds() {
        int currentDayInt = DateUtil.getDayInt(new Date());
        int lastShowDayInt = SPUtils.getInstance(configName).getInt(LAST_SPLASH_SHOW_DAY, 0);
        if (lastShowDayInt == currentDayInt) {
            return SPUtils.getInstance(configName).getString(SHOWED_POP_AD_IDS, "");
        } else {
            return "";
        }
    }

    public void saveLastShowAd(AdInfo adInfo) {
        if (adInfo == null) {
            return;
        }
        adInfo.setShowed(true);
        checkOrderAdInfos(adInfo);
        SPUtils.getInstance(configName).put(LAST_AD_CODE, adInfo.getOrder());
        int showDay = DateUtil.getDayInt(new Date());
        SPUtils.getInstance(configName).put(LAST_SPLASH_SHOW_DAY, showDay);
    }


    /**
     * 保存显示的广告时，检查一下对应的order的广告是否已经全部展示过了
     *
     * @param adInfo
     */
    private void checkOrderAdInfos(AdInfo adInfo) {
        List<AdInfo> adInfos = maps.get(adInfo.getOrder());
        //标志位
        boolean isAllShowed = true;
        if (adInfos == null) {
            isAllShowed = false;
        } else {
            for (AdInfo info : adInfos) {
                //如果有不满足的，则直接设为false，并且退出循环
                if (!info.isShowed()) {
                    isAllShowed = false;
                    break;
                }
            }
        }

        //如果全部都显示过了
        if (isAllShowed) {
            //获取本地存储的所有id
            String ids = getShowedAdIds();
            //拆分id到集合当中
            String[] split = ids.split(",");
            List<String> splashOrderList = new ArrayList<>(Arrays.asList(split));
            //将对应的广告设置为不显示，并且移除记录id的集合对应的id
            for (AdInfo info : adInfos) {
                //TODO 这里如果全部显示过了，那么把现在显示过的给跳过，其他的继续清空状态
                //因为有可能一个列表中只有一条数据，所以这个时候要判断是否是包含多条数据，并且是同个对象，如果满足条件，则跳过，这样子保证下次绝对不会随机到这次的广告
                if (adInfos.size() != 1 && adInfo == info) {
                    continue;
                }
                info.setShowed(false);
                splashOrderList.remove(info.getId() + "");
            }
            //剩余的id重新存储到本地
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < splashOrderList.size(); i++) {
                sb.append(splashOrderList.get(i));
                if (i != splashOrderList.size() - 1) {
                    sb.append(",");
                }
            }

            SPUtils.getInstance(configName).put(SHOWED_POP_AD_IDS, sb.toString());
        } else {
            //如果列表中还有未显示的广告
            String ids = getShowedAdIds();
            //那么直接拼接广告id存储到本地
            StringBuilder sb = new StringBuilder();
            sb.append(ids);
            if (TextUtils.isEmpty(sb.toString())) {
                sb.append(adInfo.getId());
            } else if (!ids.contains(adInfo.getId() + "")) {
                sb.append(",");
                sb.append(adInfo.getId());
            }
            SPUtils.getInstance(configName).put(SHOWED_POP_AD_IDS, sb.toString());
        }
    }

    /**
     * @return 获取广告来源 每次都会取下一个 已经最后一个则取第0个
     */
    public AdInfo getNextAdSource() {
        try {
            //上次显示广告的Order 排期
            int lastShowAdOrder = getLastSplashAdCodeInt();

            //上次读取的order返回-1 并且广告Map没有数据，则直接返回null order返回-1的情况为1：第一次安装 2：隔天
            if (lastShowAdOrder == -1 && (maps == null || maps.isEmpty())) {
                return null;
            }

            //根据广告的order取下一个键
            int mapKey = getNextMapKey(lastShowAdOrder);

            //map为null或者isEmpty的时候返回-1
            if (mapKey == -1) {
                return null;
            }
            //通过key，获取到对应的集合
            List<AdInfo> adInfos = maps.get(mapKey);
            return randomAdInfos(adInfos);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据广告类型取对应的键
     *
     * @param lastVideoAdOrder
     * @return
     */
    private int getNextMapKey(int lastVideoAdOrder) {
        //如果map为null，那么直接返回-1
        if (maps == null || maps.isEmpty()) {
            return -1;
        }
        //获取到对应的key的Set
        Set<Integer> integers = maps.keySet();
        //将Key的Set转为List
        ArrayList<Integer> arrayList = new ArrayList<>(integers);
        //如果传入的key为-1，那么直接返回list的map中的第一个key
        if (lastVideoAdOrder == -1) {
            return arrayList.get(0);
        }
        //如果key的位置在list的最后一条,也返回第一个KEY
        if (arrayList.indexOf(lastVideoAdOrder) == arrayList.size() - 1) {
            return arrayList.get(0);
        }
        //否则读取key所在的位置，进行++操作再返回
        int indexOf = arrayList.indexOf(lastVideoAdOrder);
        return arrayList.get(++indexOf);
    }

    /**
     * 在集合中取出没有显示过的，放入新的集合当中，然后随机取出
     *
     * @param adInfos
     * @return
     */
    private AdInfo randomAdInfos(List<AdInfo> adInfos) {
        //创建一个新的列表
        ArrayList<AdInfo> noShowedList = new ArrayList<>();
        //循环获取没有显示过的广告
        for (AdInfo adInfo : adInfos) {
            //如果广告没有显示过，则添加到新列表中
            LogUtils.e("!adInfo.isShowed()      " + (!adInfo.isShowed()));
            if (!adInfo.isShowed()) {
                noShowedList.add(adInfo);
            }
        }

        if (noShowedList.size() == 0) {
            for (AdInfo adInfo : adInfos) {
                adInfo.setShowed(false);
            }
            int i = new Random().nextInt(adInfos.size());
            return adInfos.get(i);
        } else {
            int i = new Random().nextInt(noShowedList.size());
            return noShowedList.get(i);
        }
    }

    /**
     * @return 获取本地的开屏广告来源
     */
    public String getLocalAdSource() {
        try {
            int checkCount = 0;
            String lastSplashAdCode = getLastAdCode();
            String splashAdOrder = getSplashAdOrder();
            if (!TextUtils.isEmpty(splashAdOrder)) {
                String[] splashOrderArray = splashAdOrder.split(",");
                if (splashOrderArray.length > 0) {
                    List<String> splashOrderList = new ArrayList<>(Arrays.asList(splashOrderArray));
                    splashOrderList.remove(lastSplashAdCode);
                    int lastSplashOrderIndex = splashOrderList.indexOf(lastSplashAdCode);
                    int splashAdCodeIndex = 0;
                    if (lastSplashOrderIndex != -1) {
                        splashAdCodeIndex = (lastSplashOrderIndex + 1) % splashOrderList.size();
                    }
                    while (checkCount < splashOrderList.size()) {
                        String splashAdCode = splashOrderList.get(splashAdCodeIndex % splashOrderList.size());
                        if ((AD_SOURCE_GDT.equals(splashAdCode) && AdConfig.canShowGDTAd())
                                || (AD_SOURCE_TT.equals(splashAdCode) && AdConfig.canShowCSJAd())
                                || (AD_SOURCE_SELF.equals(splashAdCode) && AdConfig.canShowSelfAd())
                        ) {
                            return splashAdCode;
                        } else {
                            splashAdCodeIndex++;
                            checkCount++;
                        }
                    }
                }
            }
        } catch (Exception e) {
            LogUtils.e(e.getMessage());
        }
        return AD_SOURCE_DEFAULT;
    }

    /**
     * 获取上次开屏的序号
     *
     * @return
     */
    public String getLastAdCode() {
        int currentDayInt = DateUtil.getDayInt(new Date());
        int lastShowDayInt = SPUtils.getInstance(configName).getInt(LAST_SPLASH_SHOW_DAY, 0);
        if (lastShowDayInt == currentDayInt) {
            return SPUtils.getInstance(configName).getString(LAST_AD_OLD_TYPE, "");
        } else {
            return "";
        }
    }

    /**
     * @return 获取开屏广告顺序
     */
    private String getSplashAdOrder() {
        return SPUtils.getInstance(configName).getString(SHOW_AD_ORDER, DEFAULT_AD_ORDER);
    }

    /**
     * 保存每次新协议已经读取的code,并且对应老的code
     *
     * @param adInfo
     */
    public void saveLastShowLocalAdCode(AdInfo adInfo) {
        switch (adInfo.getType()) {
            case AdInfo.AD_TYPE_GUANG_DIAN_TONG:
                SPUtils.getInstance(configName).put(LAST_AD_OLD_TYPE, AD_SOURCE_GDT);
                break;
            case AdInfo.AD_TYPE_CHUAN_SHAN_JIA:
                SPUtils.getInstance(configName).put(LAST_AD_OLD_TYPE, AD_SOURCE_TT);
                break;
            case AdInfo.AD_TYPE_APK:
            case AdInfo.AD_TYPE_WEB:
            case AdInfo.AD_TYPE_DEEPLINK:
                SPUtils.getInstance(configName).put(LAST_AD_OLD_TYPE, AD_SOURCE_SELF);
                break;
        }
        int showDay = DateUtil.getDayInt(new Date());
        SPUtils.getInstance(configName).put(LAST_SPLASH_SHOW_DAY, showDay);
    }

    public void saveLastShowLocalAdCode(String code){
        SPUtils.getInstance(configName).put(LAST_AD_OLD_TYPE, code);
        int showDay = DateUtil.getDayInt(new Date());
        SPUtils.getInstance(configName).put(LAST_SPLASH_SHOW_DAY, showDay);
    }
}
